﻿using AutoMapper;
using HamcoWcs.Contract.ContractCommon;
using HamcoWcs.Contract.ContractMes;
using HamcoWcs.DAL;
using HamcoWcs.Models.Common;
using HamcoWcs.Models.ForeEndModels.Basic;
using HamcoWcs.Models.ForeEndModels.Wms;
using HamcoWcs.Models.TibcoMessage;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json.Serialization;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using HamcoWcs.Models.Exceptions;
using HamcoWcs.Models.TibcoMessage.Items;
using HamcoWcs.Entitys.PalletInfos;
using HamcoWcs.Entitys.WcsLocations;
using Microsoft.EntityFrameworkCore.Internal;
using Microsoft.AspNetCore.Mvc.RazorPages;
using NPOI.SS.Formula.Functions;
using System.Drawing;
using HamcoWcs.Models.MainTasks;

namespace HamcoWcs.Main.Controllers.Wcs
{
    /// <summary>货架控制器</summary>
    public class LocationController : BasicController
    {
        #region [获取货架级联信息]

        /// <summary>获取货架级联信息</summary>
        [HttpPost]
        public IActionResult GetLocationCascader()
        {
            try
            {
                var locCascader = _locationService.GetLocationCascader();
                //var saveFlag = 0;

                return Json(new ForeEndResult(locCascader), DEFAULT_JSON_SETTINGS);
            }
            catch (Exception ex)
            {
                AddSystemLog(ex.Message);
                return QueryFailureResult();
            }
        }

        #endregion [获取货架级联信息]

        #region [修改货架锁定]

        /// <summary>修改货架锁定</summary>
        [HttpPost]
        public IActionResult UpdateWcsLock(WcsLocUpdateDto update, [FromHeader] string userName = "")
        {
            try
            {
                var loc = _wcsDbContext.WcsLocations.FirstOrDefault(d => d.WcsLocName == update.WcsLocName)
                    ?? throw new WcsRunException(update.WcsLocName, $"修改货架{update.WcsLocName}锁定状态时未找到货架");

                if (!string.IsNullOrEmpty(update.Remark))
                {
                    update.Remark = $"[{DateTime.Now:g}]{userName}:{update.Remark}";
                }

                loc.IsLock = update.IsLock;
                loc.Remark = update.Remark;

                string remark = $"{userName}修改货位{update.WcsLocName}锁定状态为 {(update.IsLock ? "锁定" : "解锁")}";
                //_loggerService.AddOperationLog(userName, loc.UnitId, update.WcsLocName, remark);
                AddOperationLog(userName, remark, loc.UnitId, "SHELF");
                _wcsDbContext.SaveChanges();


                var zoneName = loc.ZoneName;
                var machineName = loc.ZoneName.Substring(0, 8);

                var zoneData = _locationService.InventoryZonesByZone(zoneName);
                _mesCommunicateService.InventoryZoneDataRequest(new InventoryZoneDataReportMessage(new InventoryZoneDataReportMessageBody(machineName, zoneData)));

                if (!string.IsNullOrEmpty(loc.UnitId))
                {
                    _locationService.InventoryPallet(zoneName);

                    _mesCommunicateService.PalletLocStateChanged(loc);


                    //var pallet = new Pallet()
                    //{
                    //    CurrentPositionName = loc.WcsLocName,
                    //    CurrentPositionType = "SHELF",
                    //    CurrentZoneName = zoneName,
                    //    PalletLocState = loc.IsLock ? "BLOCKED" : "UNBLOCKED",
                    //    PalletName = loc.UnitId,
                    //    TransferState = "INSTK"
                    //};


                    //var body = new InventoryPalletDataReportMessageBody(machineName, new List<Pallet> { pallet });
                    //_mesCommunicateService.InventoryPalletDataRequest(new InventoryPalletDataReportMessage(body));
                }

                return Json(ForeEndResult.Ok);
            }
            catch (WcsRunException ex)
            {
                _logger.AddWcsRunLog(ex);
                return Json(ForeEndResult.Fail(ex.Message));
            }
            catch (Exception ex)
            {
                AddSystemLog(ex.Message);
                return UnknownExceptionResult();
            }
        }

        #endregion [修改货架锁定]

        #region [批量修改货架锁定]

        /// <summary>批量修改货架锁定</summary>
        [HttpPost]
        public IActionResult UpdateWcsLockRange(List<WcsLocUpdateDto> updates, [FromHeader] string userName = "")
        {
            if (updates.Count == 0) return Json(ForeEndResult.Fail("传入数据为空"));

            try
            {
                List<string> zoneNames = new List<string>();
                foreach (var update in updates)
                {
                    var loc = _wcsDbContext.WcsLocations.FirstOrDefault(d => d.WcsLocName == update.WcsLocName);
                    if (loc == null || loc.IsLock == update.IsLock) continue;
                    loc.IsLock = update.IsLock;

                    zoneNames.Add(loc.ZoneName);
                    loc.Remark = $"[{DateTime.Now:g}] {userName} : 批量锁定";
                    //_loggerService.AddOperationLog(userName, "LocationController", update.WcsLocName, );
                    AddOperationLog(userName, $"{userName}修改货位{update.WcsLocName}锁定状态为 {(update.IsLock ? "锁定" : "解锁")}", loc.UnitId, "SHELF");
                }
                _wcsDbContext.SaveChanges();

                zoneNames = zoneNames.Distinct().ToList();
                _locationService.InventoryPallet(zoneNames);
                _locationService.InventoryZones();


                return Json(ForeEndResult.Ok);
            }
            catch (WcsRunException ex)
            {
                _logger.AddWcsRunLog(ex);
                return Json(ForeEndResult.Fail(ex.Message));
            }
            catch (Exception ex)
            {
                AddSystemLog(ex.Message);
                return UnknownExceptionResult();
            }
        }

        #endregion [批量修改货架锁定]

        #region [查询货架信息（分页）]


        /*
{
  "page": 1,
  "size": 20,
  "row": null,
  "bay": null,
  "lev": null,
  "wcsLocName": "",
  "unitId": "",
  "locStatus": null,
  "isLock": null,
  "aisle": "",
  "zoneName": "",
  "basicShelf": null,
  "remark": "",
  "settingCode": "",
  "palletType": ""
}
        */
        /// <summary>查询货架信息（分页）</summary>
        [HttpPost]
        public IActionResult GetWcsLocation(WcsLocationQueryDto query)
        {
            try
            {
                var t = _wcsDbContext.WcsLocations
                                .Where(x => x.LocType == "shelf")
                                .ToList();

                var unitIds = t.Select(x => x.UnitId).Distinct().ToList();

                var palletInfo = _wcsDbContext.Set<PalletInfo>().AsQueryable()
                    .AsNoTracking()
                    .Where(x => unitIds.Contains(x.UnitId))
                    .ToList();

                var data = _mapper.Map<List<UIWcsLocation>>(t);


                foreach (var loc in data)
                {
                    if (string.IsNullOrEmpty(loc.UnitId))
                    {
                        loc.PalletType = "";
                        loc.SettingCode = "";
                        continue;
                    }
                    var p = palletInfo.FirstOrDefault(x => x.UnitId == loc.UnitId);
                    if (p == null)
                    {
                        loc.PalletType = "";
                        loc.SettingCode = "";
                        continue;
                    }
                    loc.PalletType = p.PalletType;
                    try
                    {
                        if (!p.MaterialInfo.IsNullOrEmpty())
                        {
                            var materialInfo = JsonConvert.DeserializeObject<MaterialInfo>(p.MaterialInfo);
                            if (materialInfo.MaterialCount <= 5 && !loc.PalletType.StartsWith("EMPTY"))
                            {
                                loc.PalletType = "FULL";
                            }
                            if (materialInfo.MaterialCount == 0)
                            {
                                loc.PalletType = "PALLET";
                            }
                        }
                    }
                    catch { }
                    
                    loc.SettingCode = p.SettingCode;
                }

                var filter = data.AsEnumerable();

                if (query.Row != null)
                    filter = filter.Where(x => x.Row == query.Row);
                if (query.Bay != null)
                    filter = filter.Where(x => x.Bay == query.Bay);
                if (query.Lev != null)
                    filter = filter.Where(x => x.Lev == query.Lev);
                if (query.LocStatus != null)
                    filter = filter.Where(x => x.LocStatus == query.LocStatus);
                if (query.IsLock != null)
                    filter = filter.Where(x => x.IsLock == query.IsLock);
                if (query.BasicShelf != null)
                    filter = filter.Where(x => x.BasicShelf == query.BasicShelf);

                if (!string.IsNullOrEmpty(query.WcsLocName))
                    filter = filter.Where(x => x.WcsLocName.Contains(query.WcsLocName));
                if (!string.IsNullOrEmpty(query.UnitId))
                    filter = filter.Where(x => x.UnitId.Contains(query.UnitId));
                if (!string.IsNullOrEmpty(query.Aisle))
                    filter = filter.Where(x => x.Aisle.Contains(query.Aisle));
                if (!string.IsNullOrEmpty(query.ZoneName))
                    filter = filter.Where(x => x.ZoneName.Contains(query.ZoneName));
                if (!string.IsNullOrEmpty(query.Remark))
                    filter = filter.Where(x => x.Remark.Contains(query.Remark));
                if (!string.IsNullOrEmpty(query.SettingCode))
                    filter = filter.Where(x => x.SettingCode.Contains(query.SettingCode));
                if (!string.IsNullOrEmpty(query.WcsZone))
                    filter = filter.Where(x => x.WcsZone.Contains(query.WcsZone));
                if (!string.IsNullOrEmpty(query.PalletType))
                    filter = filter.Where(x => x.PalletType.Contains(query.PalletType));

                filter = filter.OrderBy(x => x.Row)
                    .ThenBy(x => x.Bay)
                    .ThenBy(x => x.Lev);


                int count = filter.Count();
                int pageCount = 0;
                try
                {
                    if (query.Page <= 0) query.Page = 1;
                    if (query.Size <= 0) query.Size = 10;
                    pageCount = ((count - 1) / query.Size) + 1;
                    filter = filter.Skip((query.Page - 1) * query.Size)
                                 .Take(query.Size);
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message);
                }


                return Json(new ForeEndResult(filter.ToList(), count, pageCount));
            }
            catch (Exception ex)
            {
                AddSystemLog(ex.Message);
                return UnknownExceptionResult();
            }
        }

        #endregion [查询货架信息（分页）]

        #region [批量修改货架区域]

        /// <summary>批量修改货架区域</summary>
        [HttpPost]
        public IActionResult UpdateWcsLocationZone(List<WcsLocationZoneDto> updates, [FromHeader] string userName = "")
        {
            if (updates.Count == 0) return Json(ForeEndResult.Fail("传入数据为空"));

            try
            {
                foreach (var update in updates)
                {
                    var loc = _wcsDbContext.WcsLocations.FirstOrDefault(d => d.WcsLocName == update.WcsLocName);
                    if (loc == null) continue;

                    var oldZone = loc.ZoneName;
                    if (oldZone == update.ZoneName) continue;
                    loc.ZoneName = update.ZoneName;
                    //_loggerService.AddOperationLog(userName, "LocationController", update.WcsLocName, $"{userName}修改货位{update.WcsLocName}区域{oldZone}->{update.ZoneName}");
                    AddOperationLog(userName, $"{userName}修改货位{update.WcsLocName}区域{oldZone}->{update.ZoneName}", loc.UnitId, "SHELF");
                }
                _wcsDbContext.SaveChanges();
                return Json(ForeEndResult.Ok);
            }
            catch (Exception ex)
            {
                AddSystemLog(ex.Message);
                return UnknownExceptionResult();
            }
        }

        #endregion [批量修改货架区域]

        #region [批量修改货架基准货架]

        /// <summary>批量修改货架基准货架</summary>
        [HttpPost]
        public IActionResult UpdateWcsLocationBasicShelf(List<WcsLocationBasicShelfDto> updates, [FromHeader] string userName = "")
        {
            if (updates.Count == 0) return Json(ForeEndResult.Fail("传入数据为空"));

            try
            {
                foreach (var update in updates)
                {
                    var loc = _wcsDbContext.WcsLocations.FirstOrDefault(d => d.WcsLocName == update.WcsLocName);
                    if (loc == null) continue;

                    var oldBasicShelf = loc.BasicShelf;
                    if (oldBasicShelf == update.BasicShelf) continue;
                    loc.BasicShelf = update.BasicShelf;
                    //_loggerService.AddOperationLog(userName, "LocationController", update.WcsLocName, $"{userName}修改货位{update.WcsLocName}基准货架{oldBasicShelf}->{update.BasicShelf}");
                    AddOperationLog(userName, $"{userName}修改货位{update.WcsLocName}基准货架{oldBasicShelf}->{update.BasicShelf}", loc.UnitId, "SHELF");
                }
                _wcsDbContext.SaveChanges();
                return Json(ForeEndResult.Ok);
            }
            catch (Exception ex)
            {
                AddSystemLog(ex.Message);
                return QueryFailureResult();
            }
        }

        #endregion[批量修改货架基准货架]

        #region [获取所有货架信息]

        /// <summary>获取所有货架信息</summary>
        [HttpPost]
        public IActionResult GetAllLocInfo()
        {
            try
            {
                var result = _locationService.GetAllLocInfo();


                return Json(result);
            }
            catch (Exception ex)
            {
                AddSystemLog(ex.Message);
                return QueryFailureResult();
            }
        }

        #endregion [获取所有货架信息]

        #region [重置货位状态]

        /// <summary>重置货位状态</summary>
        [HttpPost]
        public IActionResult ResetLocation(UILocationModel model, [FromHeader] string userName = "")
        {
            try
            {
                var loc = _wcsDbContext.WcsLocations.FirstOrDefault(x => x.WcsLocName == model.WcsLocName)
                    ?? throw new WarningException($"未找到货位{model.WcsLocName}");

                if (loc.IsLock || loc.SrmOccupyFlag) throw new WarningException($"此货位已锁定，无法重置");



                return Json(ForeEndResult.Ok);
            }
            catch (WarningException ex)
            {
                return Json(ForeEndResult.Fail(ex.Message));
            }
            catch (Exception ex)
            {
                AddSystemLog(ex.Message);
                return UnknownExceptionResult();
            }
        }

        #endregion [重置货位状态]


        #region [建账]

        /// <summary>建账</summary>
        [HttpPost]
        public IActionResult CreateAccounts(ShelfCreateAccountModel model, [FromHeader] string userName = "")
        {
            try
            {
                if (string.IsNullOrEmpty(model.WcsLocName)) throw new WarningException("传入库位名为空");


                var loc = _wcsDbContext.WcsLocations.FirstOrDefault(x => x.WcsLocName == model.WcsLocName)
                    ?? throw new WarningException($"未找到货位{model.WcsLocName}");

                var oldMsg = $"old:[UnitId:{loc.UnitId},Status:{loc.LocStatus}]";
                var newMsg = $"new:[UnitId:{model.UnitId},Status:{model.LocStatus}]";

                //if (loc.IsLock || loc.SrmOccupyFlag) throw new WarningException($"此货位已锁定，无法重置");
                loc.UnitId = model.UnitId ?? "";
                loc.LocStatus = model.LocStatus;

                _wcsDbContext.SaveChanges();

                if (!loc.ZoneName.Contains("Z6"))
                {
                    _locationService.InventoryZone(loc.ZoneName);

                    //_locationService.InventoryPallet(loc.ZoneName);
                }

                AddOperationLog(userName, $"[{model.WcsLocName}]:{oldMsg}->{newMsg}", model.UnitId);
                //_logger.AddWcsRunLog(model.UnitId, $"[{model.WcsLocName}]:UnitId:{model.UnitId},Status:{model.LocStatus}");

                return Json(ForeEndResult.Ok);
            }
            catch (WarningException ex)
            {
                return Json(ForeEndResult.Fail(ex.Message));
            }
            catch (Exception ex)
            {
                AddSystemLog(ex.Message);
                return UnknownExceptionResult();
            }
        }

        #endregion

        #region [查找托盘]

        /// <summary>查找托盘</summary>
        [HttpPost]
        public IActionResult Searchpallet(SearchPalletModel model, [FromHeader] string userName = "")
        {
            try
            {
                if (string.IsNullOrEmpty(model.UnitId)) throw new WarningException("传入的托盘号错误");
                if (model.UnitId.Trim().Length != 6) throw new WarningException("传入的托盘号错误");

                var res = _locationService.SearchPallet(model.UnitId);


                return Json(new ForeEndResult(res));
            }
            catch (WarningException ex)
            {
                return Json(ForeEndResult.Fail(ex.Message));
            }
            catch (Exception ex)
            {
                AddSystemLog(ex.Message);
                return UnknownExceptionResult();
            }
        }

        #endregion 

        #region [ct]

        private readonly ILocationService _locationService;
        private readonly IMesCommunicateService _mesCommunicateService;
        /// <summary>
        /// 控制器名
        /// </summary>
        public override string ControllerName => "LocationController";

        /// <summary>
        /// 
        /// </summary>
        /// <param name="wcsDbContext"></param>
        /// <param name="mapper"></param>
        /// <param name="loggerService"></param>
        /// <param name="locationService"></param>
        /// <param name="mesCommunicateService"></param>
        public LocationController(WcsDbContext wcsDbContext, IMapper mapper, ILoggerService loggerService, ILocationService locationService,
            IMesCommunicateService mesCommunicateService) : base(loggerService, mapper, wcsDbContext)
        {
            _locationService = locationService;
            _mesCommunicateService = mesCommunicateService;
        }

        #endregion [ct]
    }
}
